package com.ai.platform.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Clob;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by yeyingsheng on 2018/5/14.
 */
public final class ConvertUtil {
    private static Logger logger = LoggerFactory.getLogger(ConvertUtil.class);

    private static final char[] HEXCHAR = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    private ConvertUtil() {
    }

    /**
     * map<String, Object>转bean
     *
     * @param map
     * @param obj
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> obj) {
        if (map == null) {
            return null;
        }
        T t = null;
        try {
            Set<Map.Entry<String, Object>> sets = map.entrySet();
            t = obj.newInstance();
            Method[] methods = obj.getDeclaredMethods();
            for (Map.Entry<String, Object> entry : sets) {
                String str = entry.getKey();
                String setMethod = "set" + str.substring(0, 1).toUpperCase() + str.substring(1);
                for (Method method : methods) {
                    if (method.getName().equals(setMethod)) {
                        method.invoke(t, entry.getValue());
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("mapToBean Error " + e);
        }
        return t;
    }

    /**
     * Map<String, String[]> 转bean
     *
     * @param map
     * @param obj
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T mapArrayToBean(Map<String, String[]> map, Class<T> obj){
        if (map == null) {
            return null;
        }
        T t = null;
        try {
            Set<Map.Entry<String, String[]>> sets = map.entrySet();
            t = obj.newInstance();
            Method[] methods = obj.getDeclaredMethods();
            for (Map.Entry<String, String[]> entry : sets) {
                String str = entry.getKey();
                String setMethod = "set" + str.substring(0, 1).toUpperCase() + str.substring(1);
                for (Method method : methods) {
                    if (method.getName().equals(setMethod)) {
                        String[] values = entry.getValue();
                        if (null == values || values.length == 0) {
                            break;
                        }
                        if (values.length == 1) {
                            //参数类型判断
                            Class c=method.getParameterTypes()[0];
                            if(c.getName().equals("java.lang.String")){
                                method.invoke(t, values[0]);
                            }else if(c.getName().equals("java.lang.Integer")){
                                method.invoke(t, Integer.parseInt(values[0]));
                            }else if(c.getName().equals("java.lang.Long")){
                                method.invoke(t, Long.parseLong(values[0]));
                            }else if(c.getName().equals("java.lang.Boolean")){
                                method.invoke(t, Boolean.parseBoolean(values[0]));
                            }else if(c.getName().equals("java.lang.double")){
                                method.invoke(t, Double.parseDouble(values[0]));
                            }else if(c.getName().equals("java.lang.short")){
                                method.invoke(t, Short.parseShort(values[0]));
                            }else if(c.getName().equals("java.lang.float")){
                                method.invoke(t, Float.parseFloat(values[0]));
                            }
                        } else {
                            method.invoke(t, values);
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("mapArrayToBean Error " + e);
        }
        return t;
    }

    /**
     * bean转map
     *
     * @param obj
     * @return
     */
    public static Map<String, Object> beanToMap(Object obj) {
        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (!key.equals("class")) {
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }
            }
        } catch (Exception e) {
            System.out.println("beanToMap Error " + e);
        }
        return map;
    }

    /**
     * Blob转String
     *
     * @param blob
     * @return
     * @throws Exception
     */
    public static String blobToString(Blob blob) throws Exception {
        byte[] returnValue = blob.getBytes(1L, (int) blob.length());
        return bytesToString(returnValue);
    }

    /**
     * Clob转String
     *
     * @param val
     * @return
     * @throws Exception
     */
    public static String clobToString(Clob val) throws Exception {
        if (null == val) {
            return null;
        } else {
            Reader reader = null;
            StringBuffer buf = new StringBuffer();
            BufferedReader bfReader = null;

            try {
                reader = val.getCharacterStream();
                bfReader = new BufferedReader(reader);

                for (String s = bfReader.readLine(); null != s; s = bfReader.readLine()) {
                    buf.append(s);
                }
            } catch (Exception var12) {
                throw var12;
            } finally {
                try {
                    if (null != reader) {
                        reader.close();
                    }

                    if (null != bfReader) {
                        bfReader.close();
                    }
                } catch (IOException var11) {
                    throw var11;
                }

            }

            return buf.toString();
        }
    }

    /**
     * byte转String
     *
     * @param bytes
     * @return
     */
    public static String bytesToString(byte[] bytes) {
        StringBuilder builder = new StringBuilder(bytes.length * 2);

        for (int i = 0; i < bytes.length; ++i) {
            builder.append(HEXCHAR[(bytes[i] & 240) >>> 4]);
            builder.append(HEXCHAR[bytes[i] & 15]);
        }

        return builder.toString();
    }

    /**
     * String转Byte
     *
     * @param str
     * @return
     */
    public static byte[] string2Bytes(String str) {
        byte[] bytes = new byte[str.length() / 2];

        for (int i = 0; i < bytes.length; ++i) {
            bytes[i] = (byte) Integer.parseInt(str.substring(2 * i, 2 * i + 2), 16);
        }

        return bytes;
    }

    /**
     * String转InputStream
     *
     * @param str
     * @return
     */
    public static InputStream stringToInputStream(String str) {
        try {
            return new ByteArrayInputStream(string2Bytes(str));
        } catch (Exception var2) {
            logger.error("string2InputStream", "", var2);
            var2.printStackTrace();
            return null;
        }
    }

    /**
     * File转String
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static String fileToString(File file) throws Exception {
        InputStream inputStream = new FileInputStream(file);
        byte[] bytes = new byte[(int) file.length()];
        inputStream.read(bytes);
        return bytesToString(bytes);
    }

    /**
     * InputStream转String
     *
     * @param inputStream
     * @return
     * @throws Exception
     */
    public static String inputStreamToString(InputStream inputStream) throws Exception {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];

        int rc;
        while ((rc = inputStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }

        byte[] in_b = swapStream.toByteArray();
        return bytesToString(in_b);
    }
}
